package application;

import application.anno.*;
import application.anno.impl.AutoCloseImpl;
import application.anno.impl.AutoRegisterImpl;
import application.anno.impl.FXServiceImpl;
import application.anno.impl.InjectionImpl;
import application.entity.StageEntity;
import application.exception.EntranceNotUniqueException;
import application.exception.NoMainUserInterfaceException;
import application.exception.NoScannerPackageException;
import application.exception.NotFoundNecessaryAnnotationException;
import application.manager.ActivityManager;
import application.manager.InjectionManager;
import application.util.ReflectionsUtil;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.image.Image;
import javafx.stage.Stage;

import java.net.URL;
import java.util.Set;

public class Program extends Application {

    protected InjectionImpl injection;

    protected AutoRegisterImpl autoRegister;

    protected AutoCloseImpl autoClose;

    protected volatile FXServiceImpl fxService;

    @Override
    public void start(Stage primaryStage) throws Exception {
        // 通过反射工具查找所有拥有MainActivity注解的类。
        Set<Class<?>> annotationByClass = ReflectionsUtil.getAnnotationByClass(MainActivity.class);
        if (annotationByClass == null || annotationByClass.size() <= 0) {
            // 若没有注解对象，则抛出此异常，因为程序无法找到主窗口
            throw new NoMainUserInterfaceException("Not found UserInterface as entrance, please use MainActivity annotation sing entrance");
        } else if (annotationByClass.size() > 1) {
            // 如果对象超过一个，抛出此异常，因为主窗口太多，程序无法确定，谁的优先级高。
            throw new EntranceNotUniqueException("Place select entrance from in \n(\n{}\n)".replace("{}", annotationByClass.toString()));
        }
        // 获取主窗口的类对象
        Class<?> aClass = annotationByClass.iterator().next();
        Layout annotation = aClass.getAnnotation(Layout.class);
        if (annotation == null) {
            // 如果主窗口类对象上方Layout注解中的布局信息为空，则抛出此异常
            throw new NotFoundNecessaryAnnotationException("Not found Layout annotation, can not get layout resource");
        }
        // 获取窗口管理者
        ActivityManager activityManager = ActivityManager.getInstance();
        // 注册并生成主窗口
        StageEntity register = activityManager.register(annotation.value(), primaryStage);
        // 获取窗口对象
        Stage stage = register.getStage();
        // 获取窗口对象上方的StageTitle注解。
        StageTitle stageTitle = register.getController().getClass().getAnnotation(StageTitle.class);
        if (stageTitle != null) {
            // 若注解不为空，则将此信息填入窗口左上方的title中
            stage.setTitle(stageTitle.value());
        }
        // 获取窗口上方的IconName注解。
        IconName iconName = register.getController().getClass().getAnnotation(IconName.class);
        // 若IconName部位空，则将其表示的图片，贴入窗口左上方的图形组件中
        if (iconName != null && !iconName.value().isEmpty()) {
            // 获取窗口的图标管理器
            ObservableList<Image> icons = stage.getIcons();
            if (icons.size() <= 0) {
                // 生成图标在resource中的位置
                // 注意：图标只能放在resource下的image目录中
                String concat = "image/".concat(iconName.value());
                // 获取图标在resource目中的URL
                URL resource = getClass().getClassLoader().getResource(concat);
                // 添加图标到窗口左上方的图形组件中
                icons.add(new Image(resource.toString()));
            }
        }
        // 显示窗口
        stage.show();
    }

    @Override
    public void init() throws Exception {
        // 寻找子类上的ScannerPackage注解。
        ScannerPackage annotation = this.getClass().getAnnotation(ScannerPackage.class);
        if (annotation == null) {
            // 当子类找不到注解时，抛出此异常，程序将不会继续执行
            throw new NoScannerPackageException("Not found ScannerPackage annotation, place use ScannerPackage in main class and input package information");
        }
        // 获取注解中的完整包名，并且初始化反射工具。
        ReflectionsUtil.init(annotation.value());

        // 自动注册AutoRegister
        if (autoRegister == null) {
            autoRegister = new AutoRegisterImpl();
        }
        autoRegister.registerListClass();

        // 自动注入Injection
        if (injection == null) {
            injection = new InjectionImpl();
        }
        injection.injectionField();
        InjectionManager.getInstance().register(this.getClass(), this);
        // 自动注册Service组件
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (fxService == null) {
                    fxService = new FXServiceImpl();
                }
                fxService.startService();
            }
        }).start();
    }

    @Override
    public void stop() throws Exception {
        super.stop();

        // 自动注销Unregister注解
        if (autoClose == null) {
            autoClose = new AutoCloseImpl();
        }
        autoClose.unregisterListClass();

        // 自动关闭Service
        if (fxService == null) {
            fxService = new FXServiceImpl();
        }
        fxService.close();
    }
}
